<?php
namespace Model;

require_once 'Model.php';
require_once 'Attribut.php';
require_once 'AnnonceAttribut.php';

use Model\Model;
use Model\Attribut;
use Model\AnnonceAttribut;
use Classes\Field;
use Classes\Filter;
use Classes\Upload;

class Annonce extends Model {
    private $table = 'annonce';
    public $id_annonce;
    public $statut;
    public $attributs;
    public $attrHtml;
    public $attrLibelle;
    
    public function __construct($data = array()) {
        parent::__construct();
        $this->id_annonce = isset($data['id_annonce'])?$data['id_annonce']:null;
        $this->active = isset($data['active'])?$data['active']:null;
        $this->attributs = isset($data['attributs'])?$data['attributs']:null;
        $this->attrHtml = isset($data['attrHtml'])?$data['attrHtml']:null;
        $this->attrLibelle = isset($data['attrLibelle'])?$data['attrLibelle']:null;
    }
    
    /**
     * Retourne une liste des annonces
     * @param string $where : Clause where de la requete
     * @param string $sort : Nom du champ sur lequel s'effectue le tri
     * @param string $sortdir : Sens du tri
     * @param int $limit_start : Position à partir duquel on récupère les enregistrements
     * @param int $items_per_page : Nombre d'enregistrement à afficher par page
     * @return array $result
     */
    public function fetchAll($where, $sort='a.id_annonce', $sortdir='ASC', $limit_start=null, $items_per_page=null) {
        $attributObject = new Attribut();
        $attributs = $attributObject->fetchAll(1);        
        $query = 'SELECT DISTINCT a.id_annonce';
        
        foreach($attributs as $attribut) {
            $query .= ', (SELECT value'
                    . ' FROM annonce_attribut AS aa'
                    . ' WHERE aa.id_annonce = a.id_annonce'
                    . ' AND aa.id_attribut = '.$attribut->id_attribut.') AS '.$attribut->alias;
        }
        $query .= ' FROM '.$this->table.' AS a'
                . ' JOIN annonce_attribut AS aa'
                . ' ON (a.id_annonce = aa.id_annonce)'
                . ' WHERE '.$where;
        
        // Si un tri sur un champ est demandé
        if($sort && $sortdir) {
            $orderby = ' ORDER BY '.$sort.' '.$sortdir;
        } elseif($sort && !$sortdir) {
            $orderby = ' ORDER BY '.$sort;
        } else {
            $orderby = ' ORDER BY a.id_annonce ASC';
        }
        $query .= $orderby;
        
        // Si une pagination sur les résultats est demandée
        if($limit_start && $items_per_page) { 
            $limit = ' LIMIT '.$limit_start.', '.$items_per_page; 
            
        } elseif(!$limit_start && $items_per_page) { 
            $limit = ' LIMIT '.$items_per_page;             
        } else { 
            $limit = '';            
        }
        $query .= $limit;
        
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        //echo $select->queryString;
        try {
            $select->execute();
            $result = $select->fetchAll();
            $cols = $attributObject->fetchAllCol();
            foreach($result as $res) {
                foreach($cols as $col) {
                    $alias = $col->alias;
                    $resValue = $res->$alias;
                    
                    // Retourne l'option correspondante à la valeur (SELECT, RADIO)
                    if($col->predefined_option && ($col->type==Field::SELECT || $col->type==Field::RADIO)) {
                        $pOptions = explode(',', $col->predefined_option);
                        $pValues = explode(',', $col->predefined_value);
                        foreach($pValues as $idx => $pValue) {
                            if($resValue == $pValue) {
                                $res->$alias = $pOptions[$idx];
                            }
                        }    
                    }
                    
                    // Retourne les options correspondantes à la valeur (CHECKBOX)
                    if($col->predefined_option && $col->type==Field::CHECKBOX) {
                        $valueText = '';
                        $pOptions = explode(',', $col->predefined_option);
                        $pValues = explode(',', $col->predefined_value);
                        foreach($pValues as $idx => $pValue) {
                            $values = explode(',', $resValue);
                            foreach($values as $value) {
                                if($value == $pValue) {
                                    $valueText .= ($valueText)?','.$pOptions[$idx]:$pOptions[$idx];
                                }
                            }
                        } 
                        $res->$alias = $valueText;
                    }
                    
                    // Retourne une date formatée
                    if($resValue && ($col->type==Field::DATE || $col->type==Field::DATEHIDDEN)) {
                        $date = new \DateTime($resValue);
                        $res->$alias = $date->format('d-M-Y');
                    }
                }
            }
            return $result;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }        
    }
    
    /**
     * Retourne une annonce
     * @param int $id_annonce : Id de l'annonce à récupérer
     * @param boolean $html : Spécifie si l'on veut avoir le rendu html
     * @return object $result
     */
    public function getAnnonce($id_annonce, $html=false) { 
        $data = array();
        $id_annonce = (int) $id_annonce;
        $attributObject = new Attribut(); 
        $annonceAttributObject = new AnnonceAttribut();
        $query = 'SELECT *'
                . ' FROM '.$this->table
                . ' WHERE id_annonce = '.$id_annonce;
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {
            $select->execute();
            $result = $select->fetch();
            
            $data['id_annonce'] = isset($result->id_annonce)?$result->id_annonce:null;
            $data['active'] = isset($result->active)?$result->active:null;
            
            // Récupération des attributs actifs de l'annonce
            $attributs = $attributObject->fetchAll(1, null, null, null, null, $data['id_annonce'], $html);
            
            // Récupération des valeurs des attributs
            foreach($attributs as $attribut) {                 
                $data['attributs'][$attribut->alias] = $attribut->value;
                $data['attrHtml'][$attribut->alias] = $attribut->html;
                $data['attrLibelle'][$attribut->alias] = $attribut->libelle;
            }
            
            // Retourne l'objet
            return new Annonce($data);
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Retourne une annonce vide prêt à être rempli
     * @return object $result
     */
    public function newAnnonce() {  
        $data = array();
        $attributObject = new Attribut(); 
        $annonceAttributObject = new AnnonceAttribut();
        $query = 'SELECT *'
                . ' FROM '.$this->table
                . ' WHERE id_annonce = NULL';
        $select = $this->db->prepare($query);
        $select->setFetchMode(\PDO::FETCH_OBJ);
        try {
            $select->execute();
            $result = $select->fetch();
            
            $data['id_annonce'] = isset($result->id_annonce)?$result->id_annonce:null;
            $data['active'] = isset($result->active)?$result->active:null;
            
            // Récupération des attributs actifs de l'annonce
            $attributs = $attributObject->fetchAll(1, null, null, null, null, $data['id_annonce'], true);
            
            // Récupération des valeurs des attributs
            foreach($attributs as $attribut) {
                $value = $annonceAttributObject->getAnnonceAttribut(null, $attribut->id_attribut);
                $data['attributs'][$attribut->alias] = ($value)?$value->value:NULL;
                $data['attrHtml'][$attribut->alias] = $attribut->html;
                $data['attrLibelle'][$attribut->alias] = $attribut->libelle;
            }
            
            // Retourne l'objet
            return new Annonce($data);
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Enregistre une insertion ou une modification d'une annonce
     * @param array $data : Données à enregistrer dans la table "annonce"
     * @param array $attrData : Données à enregistrer dans la table "annonce_attribut"
     */
    public function saveAnnonce($data, $attrData) {
        $id_annonce = (int) $data['id_annonce'];
        $upload = new Upload();
        $attributObject = new Attribut();
        $annonceAttributObject = new AnnonceAttribut();
        if($id_annonce == 0) {
            $query = 'INSERT INTO '.$this->table.' VALUES ('
                    . ' :id_annonce,'
                    . ' :statut)';
            $insert = $this->db->prepare($query);
            try {
                // Insert l'annonce
                $insert->execute($data);
                $lastInsertId = $this->db->lastInsertId();
                
                // Enregistrement des valeurs des attributs
                $attributs = $attributObject->fetchAll(1);
                foreach($attributs as $attribut) {
                    $value = '';
                    if(isset($attrData[$attribut->alias])) {
                        $value = $attrData[$attribut->alias];                        
                    }
                    $value = (is_array($value))? implode(',', $value):$value;
                    $id_attribut = $attributObject->getAttributByAlias($attribut->alias)->id_attribut;
                        $aaData = array(
                        'id_annonce' => $lastInsertId,
                        'id_attribut' => $id_attribut,
                        'value' => $value
                    );
                    $annonceAttributObject->saveAnnonceAttribut($aaData);
                }
                $return = array();
                
                // Teste si des images et/ou des fichiers ont été uploadés
                if(isset($attrData[Upload::FILES_INDEX])) {
                    $upload->getFiles($attrData[Upload::FILES_INDEX]);
                    $results = $upload->process();
                    foreach($results as $alias => $result) {
                        if($result['code'] == Upload::SUCCESS_CODE) {
                            $id_attribut = $attributObject->getAttributByAlias($alias)->id_attribut;
                            $aaData = array(
                                'id_annonce' => $lastInsertId,
                                'id_attribut' => $id_attribut,
                                'value' => $result['file']
                            );
                            $annonceAttributObject->saveAnnonceAttribut($aaData);
                        } else {
                            $return[] = $result;
                        }
                    }
                }
                return $return;
            } catch (Exception $ex) {
                echo 'Erreur de requète : ', $ex->getMessage();
            }
        } else {
            $query = 'UPDATE '.$this->table.' SET'
                    . ' id_annonce = :id_annonce,'
                    . ' statut = :statut'
                    . ' WHERE id_annonce = '.$id_annonce;
            $update = $this->db->prepare($query);
            try {
                // Modifie l'annonce
                $update->execute($data);
                
                // Enregistrement des valeurs des attributs
                $attributs = $attributObject->fetchAll(1);
                foreach($attributs as $attribut) {
                    $value = '';
                    if(isset($attrData[$attribut->alias])) {
                        $value = $attrData[$attribut->alias];
                    }
                    $value = (is_array($value))? implode(',', $value):$value;
                    $id_attribut = $attributObject->getAttributByAlias($attribut->alias)->id_attribut;
                    $type = $attributObject->getAttributByAlias($attribut->alias)->type;
                    if($type != Field::IMAGE && $type != Field::FILE) {
                        $aaData = array(
                            'id_annonce' => $id_annonce,
                            'id_attribut' => $id_attribut,
                            'value' => $value
                        );
                        $annonceAttributObject->saveAnnonceAttribut($aaData);
                    }
                }
                $return = array();
                
                // Teste si des images et/ou des fichiers ont été uploadés
                if(isset($attrData[Upload::FILES_INDEX])) {
                    $upload->getFiles($attrData[Upload::FILES_INDEX]);
                    $results = $upload->process();
                    foreach($results as $alias => $result) {
                        if($result['code'] == Upload::SUCCESS_CODE) {                            
                            $id_attribut = $attributObject->getAttributByAlias($alias)->id_attribut;
                            
                            // Récupère et supprime l'ancienne image si existant
                            $oldValue = $annonceAttributObject->getAnnonceAttribut($id_annonce, $id_attribut);
                            if($oldValue && $oldValue->value != "") {
                                $filename = $oldValue->value;
                                $upload->deleteFile($filename);
                            }
                            
                            // Prépare la nouvelle valeur
                            $aaData = array(
                                'id_annonce' => $id_annonce,
                                'id_attribut' => $id_attribut,
                                'value' => $result['file']
                            );
                            $annonceAttributObject->saveAnnonceAttribut($aaData);
                        } else {
                            $return[$alias] = $result;
                        }
                    }
                }                
                return $return;
            } catch (Exception $ex) {
                echo 'Erreur de requète : ', $ex->getMessage();
            }
        }
    }
    
    /**
     * Supprime une annonce
     * @param int $id_annonce : Id de l'annonce à supprimer
     */
    public function deleteAnnonce($id_annonce) {
        $id_annonce = (int) $id_annonce;
        $upload = new Upload();
        $attributObject = new Attribut();
        $annonceAttributObject = new AnnonceAttribut();
        $query = 'DELETE'
                . ' FROM '.$this->table
                . ' WHERE id_annonce = '.$id_annonce;
        try {
            // Supprime les fichiers ou les images relatifs à l'annonce
            $attributs = $attributObject->fetchAll(1);
            foreach($attributs as $attribut) {
                if($attribut->type == Field::IMAGE || $attribut->type == Field::FILE) {
                    $value = $annonceAttributObject->getAnnonceAttribut($id_annonce, $attribut->id_attribut);
                    if($value && $value->value != "") {
                        $upload->deleteFile($value->value);
                    }
                }
            }
            
            // Supprime les attributs relatifs à l'annonce
            $annonceAttributObject->deleteAnnonceAttribut($id_annonce);
            
            // Supprime l'annonce
            $this->db->exec($query);
            return true;
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
    
    /**
     * Met à jour le statut d'une annonce
     * @param int $id_annonce : Id de l'annonce à mettre à jour
     * @param int $statut : Statut voulue pour l'annonce
     */
    public function changeStatut($id_annonce, $statut) {
        $id_annonce = (int)$id_annonce;
        $query = 'UPDATE '.$this->table.' SET'
                . ' statut = :statut'
                . ' WHERE id_annonce = '.$id_annonce;
        $update = $this->db->prepare($query);
        try {
            $data = array('statut' => (int)$statut);
            $update->execute($data);
        } catch (Exception $ex) {
            echo 'Erreur de requète : ', $ex->getMessage();
        }
    }
}
